View Javadoc
1   package org.apache.maven.surefire.common.junit4;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.surefire.report.SafeThrowable;
23  import org.apache.maven.surefire.report.SmartStackTraceParser;
24  import org.apache.maven.surefire.report.StackTraceWriter;
25  
26  import org.junit.runner.notification.Failure;
27  
28  /**
29   * Writes out a specific {@link org.junit.runner.notification.Failure} for
30   * surefire as a stacktrace.
31   *
32   * @author Karl M. Davis
33   */
34  public class JUnit4StackTraceWriter
35      implements StackTraceWriter
36  {
37      // Member Variables
38      protected final Failure junitFailure;
39  
40      /**
41       * Constructor.
42       *
43       * @param junitFailure the {@link Failure} that this will be operating on
44       */
45      public JUnit4StackTraceWriter( Failure junitFailure )
46      {
47          this.junitFailure = junitFailure;
48      }
49  
50      /*
51        * (non-Javadoc)
52        *
53        * @see org.apache.maven.surefire.report.StackTraceWriter#writeTraceToString()
54        */
55      public String writeTraceToString()
56      {
57          Throwable t = junitFailure.getException();
58          if ( t != null )
59          {
60              String originalTrace = junitFailure.getTrace();
61              if ( isMultiLineExceptionMessage( t ) )
62              {
63                  // SUREFIRE-986
64                  StringBuilder builder = new StringBuilder( originalTrace );
65                  String exc = t.getClass().getName() + ": ";
66                  if ( originalTrace.startsWith( exc ) )
67                  {
68                      builder.insert( exc.length(), '\n' );
69                  }
70                  return builder.toString();
71              }
72              return originalTrace;
73          }
74          return "";
75      }
76  
77  
78      protected String getTestClassName()
79      {
80          return JUnit4RunListener.extractClassName( junitFailure.getDescription() );
81      }
82  
83      protected String getTestMethodName()
84      {
85          return JUnit4RunListener.extractMethodName( junitFailure.getDescription() );
86      }
87  
88      @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" )
89      public String smartTrimmedStackTrace()
90      {
91          Throwable exception = junitFailure.getException();
92          return exception == null
93              ? junitFailure.getMessage()
94              : new SmartStackTraceParser( getTestClassName(), exception, getTestMethodName() ).getString();
95      }
96  
97      /**
98       * At the moment, returns the same as {@link #writeTraceToString()}.
99       *
100      * @see org.apache.maven.surefire.report.StackTraceWriter#writeTrimmedTraceToString()
101      */
102     public String writeTrimmedTraceToString()
103     {
104         String testClass = getTestClassName();
105         try
106         {
107             Throwable e = junitFailure.getException();
108             return SmartStackTraceParser.stackTraceWithFocusOnClassAsString( e, testClass );
109         }
110         catch ( Throwable t )
111         {
112             return SmartStackTraceParser.stackTraceWithFocusOnClassAsString( t, testClass );
113         }
114     }
115 
116     /**
117      * Returns the exception associated with this failure.
118      *
119      * @see org.apache.maven.surefire.report.StackTraceWriter#getThrowable()
120      */
121     public SafeThrowable getThrowable()
122     {
123         return new SafeThrowable( junitFailure.getException() );
124     }
125 
126     private static boolean isMultiLineExceptionMessage( Throwable t )
127     {
128         String msg = t.getLocalizedMessage();
129         if ( msg != null )
130         {
131             int countNewLines = 0;
132             for ( int i = 0, length = msg.length(); i < length; i++ )
133             {
134                 if ( msg.charAt( i ) == '\n' )
135                 {
136                     if ( ++countNewLines == 2 )
137                     {
138                         break;
139                     }
140                 }
141             }
142             return countNewLines > 1 || countNewLines == 1 && !msg.trim().endsWith( "\n" );
143         }
144         return false;
145     }
146 
147 }